
/*
MAIN PROGRAM ENTRANCE
Enter command lines to operate。
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class Program {
	public static int studentNum;
	public static ArrayList<Student> students = new ArrayList<Student>();

	static void createDefault(int num) {
		for (int i = 0; i < num; i++) {
			Random g = new Random();
			// students.add(new Student("Student" + String.valueOf(i + 1), g.nextInt(101)));
			students.add(new Student(NameGenerator.generateName(), g.nextInt(101)));
			studentNum++;
		}
	}

	static void readData() { // read students' data into studentsData.txt;
		// format: studentsNum
		// (name\ngrade)*studentNum
		try {
			File studentDatabase = new File("studentsData.txt");
			try {
				FileReader fr = new FileReader(studentDatabase);
				BufferedReader br = new BufferedReader(fr);
				studentNum = Integer.parseInt(br.readLine());// 读取学生数
				for (int i = 1; i <= studentNum; i++) {
					students.add(new Student(br.readLine(), Integer.parseInt(br.readLine())));// stu's info
				}
				br.close();
			} catch (FileNotFoundException e) {// use default if not created
				createDefault(100);
			}
		} catch (IOException ex) {
			System.out.println("IOException");
		}
	}

	static void writeData() {// write students' data into studentsData.txt;
		// format: studentsNum
		// (name\ngrade)*studentNum
		try {
			File studentDatabase = new File("studentsData.txt");
			if (studentDatabase.exists()) { // Rewrite
				studentDatabase.delete();
			}
			studentDatabase.createNewFile();
			try {
				FileWriter fw = new FileWriter(studentDatabase);
				BufferedWriter bw = new BufferedWriter(fw);
				bw.write(String.valueOf(studentNum) + "\n");
				for (int i = 1; i <= studentNum; i++) {
					bw.write(students.get(i - 1).name + "\n");// write name
					bw.write(String.valueOf(students.get(i - 1).grade) + "\n");// write grade
				}
				bw.flush();
				bw.close();
			} catch (Exception e) { // NO BUGS!!!!
				System.out.println("IOException");
			}
		} catch (IOException e) { // NO BUGS!!!!
			System.out.println("IOException");
		}
	}

	static void qSort(int h, int t) { // Quicksort.
		if (h >= t) {
			return;
		}
		int i = h;
		int j = t;
		Student key = students.get(i);
		while (i < j) {
			while (i < j && students.get(j).compareTo(key) >= 0) {
				j--;
			}
			while (i < j && students.get(i).compareTo(key) <= 0) {
				i++;
			}
			if (i < j) {
				Student temp = students.get(i);
				students.set(i, students.get(j));
				students.set(j, temp);
			}
		}
		students.set(h, students.get(i));
		students.set(i, key);
		qSort(h, i - 1);
		qSort(i + 1, t);
	}

	static void qSortName(int h, int t) { // Quicksort by name.
		if (h >= t) {
			return;
		}
		int i = h;
		int j = t;
		Student key = students.get(i);
		while (i < j) {
			while (i < j && students.get(j).name.compareTo(key.name) >= 0) {
				j--;
			}
			while (i < j && students.get(i).name.compareTo(key.name) <= 0) {
				i++;
			}
			if (i < j) {
				Student temp = students.get(i);
				students.set(i, students.get(j));
				students.set(j, temp);
			}
		}
		students.set(h, students.get(i));
		students.set(i, key);
		qSortName(h, i - 1);
		qSortName(i + 1, t);
	}

	static void quickSortStudents() { // Sort the students. Method: Quicksort
		qSort(0, studentNum - 1);
	}

	static void sortStudentsByName() { // Sort the students by name;
		qSortName(0, studentNum - 1);
	}

	static void addStudent(Student s) { // add a student s;
		studentNum++;
		students.add(s);
	}

	static void deleteStudent(Student s) { // delete one student s;
		Boolean flag = students.remove(s);
		if (!flag) {
			IndexOutOfBoundsException e = new IndexOutOfBoundsException();
			throw e;
		}
		studentNum--;
	}

	static Student deleteStudent(int stuNum) { // delete the student at stuNum.
		sortStudentsByName();
		if (studentNum < 1 || stuNum > studentNum) {
			IndexOutOfBoundsException e = new IndexOutOfBoundsException();
			throw e;
		}
		studentNum--;
		Student ans = students.get(stuNum - 1);
		students.remove(stuNum - 1);
		return ans;
	}

	static void clear() {
		studentNum = 0;
		students.clear();
	}

	static void printRank() { // Print the score board
		quickSortStudents();
		System.out.println("Students' Rank:");
		for (int i = 0; i < studentNum; i++) {
			System.out.println("Rank#" + String.valueOf(i + 1) + "\t\t" + students.get(i));
		}
	}

	static void printStudentList() { // print the students by name lex order.
		sortStudentsByName();
		System.out.println("Student List:");
		for (int i = 0; i < studentNum; i++) {
			System.out.println(String.valueOf(i + 1) + ".\t\t" + students.get(i));
		}
	}

	static void Search(String keyword) { // search a student by name
		int sum = 0;
		sortStudentsByName();
		for (int i = 0; i < studentNum; i++) {
			if (students.get(i).name.equals(keyword)) {
				System.out.println(String.valueOf(i + 1) + ". " + students.get(i));
				sum++;
			}
		}
		for (int i = 0; i < studentNum; i++) {
			if (!students.get(i).name.equals(keyword) && students.get(i).name.replaceAll(" ", "").toLowerCase()
					.contains(keyword.replaceAll(" ", "").toLowerCase())) {
				System.out.println(String.valueOf(i + 1) + ". " + students.get(i));
				sum++;
			}
		}
		System.out.print(String.valueOf(sum) + "result");
		if (sum > 1) {
			System.out.print("s");
		}
		System.out.println(".");
	}

	public static void main(String[] args) { // Imitate terminal
		readData();
		Scanner sc = new Scanner(System.in);
		System.out.println("Students Client created by Gu Zhenrong");
		while (true) {
			System.out.print(">>>"); // 开头字符
			String temp;
			temp = sc.nextLine();
			Scanner sc2 = new Scanner(temp);
			String w1 = sc2.next();
			if (w1.equals("quit")) {
				sc2.close();
				break;
			} else if (w1.equals("help")) {
				if (!sc2.hasNext()) {
					System.out.print(
							"Commands:\nquit\nhelp\nrank\nlist\nadd\ndel\nclear\nsearch\nInput 'help command' to get more information, eg:'help list'\n");
					continue;
				}
				switch (sc2.nextLine().trim()) {
				case "help":
					System.out.println("Get help of something.");
					break;
				case "quit":
					System.out.println("Quit the program.");
					break;
				case "rank":
					System.out.println("Print the rank of the students");
					break;
				case "list":
					System.out.println("Print the students' list.");
					break;
				case "clear":
					System.out.println("Clear the students' list.");
					break;
				case "generate":
					System.out.println(
							"Regenerate the students' list. Format: 'generate number_of_students', eg:'generate 20'.");
					break;
				case "add":
					System.out.println(
							"Add a student to list. Format: 'add name_of_student grade_of_student', eg:'add Tom Clancy 20'.");
					break;
				case "del":
					System.out.println(
							"Delete one student from list. Format: 'del name_of_student grade_of_student', eg:'del Tom Clancy 20'.");
					break;
				case "search":
					System.out.println(
							"Search students who has name with part of key words. Format: 'search key_word', eg:'search Tom'.");
					break;
				default:
					break;
				}
			} else if (w1.equals("rank")) {
				printRank();
			} else if (w1.equals("list")) {
				printStudentList();
			} else if (w1.equals("clear")) {
				clear();
				System.out.println("Successfully cleared.");
				writeData();
			} else if (w1.equals("generate")) {
				if (sc2.hasNextInt()) {
					clear();
					createDefault(sc2.nextInt());
					System.out.println("Successfully regenerated.");
					writeData();
				} else {
					System.out.println(
							"Syntax of inputs exception. Format: 'generate number_of_students', eg:'generate 20'.");
				}
			} else if (w1.equals("add")) {
				try {
					String nme = "";
					while (sc2.hasNext() && !sc2.hasNextInt()) {
						nme += sc2.next() + " ";
					}
					nme = nme.trim();
					int grd = sc2.nextInt();
					addStudent(new Student(nme, grd));
					System.out.println("Successfully add student " + new Student(nme, grd));
					writeData();
				} catch (Exception e) {
					System.out.println(
							"Syntax of inputs exception. Format: 'add name_of_student grade_of_student', eg:'add Tom Clancy 20'.");
				}
			} else if (w1.equals("del")) {
				try {
					if (sc2.hasNext() && !sc2.hasNextInt()) {
						String nme = "";
						while (sc2.hasNext() && !sc2.hasNextInt()) {
							nme += sc2.next() + " ";
						}
						nme = nme.trim();
						int grd = sc2.nextInt();
						deleteStudent(new Student(nme, grd));
						System.out.println("Successfully delete " + new Student(nme, grd));
						writeData();
					} else if (sc2.hasNextInt()) {
						System.out.println("Successfully delete " + deleteStudent(sc2.nextInt()));
						writeData();
					} else {
						System.out.println(
								"Syntax of inputs exception. Format: 'del name_of_student grade_of_student' OR 'del stu_num', eg:'del Tom Clancy 20' OR 'del 12'.");
					}
				} catch (IndexOutOfBoundsException e) {
					System.out.println("There is no this student.");
				} catch (Exception e) {
					System.out.println(
							"Syntax of inputs exception. Format: 'del name_of_student grade_of_student' OR 'del stu_num', eg:'del Tom Clancy 20' OR 'del 12'.");
				}
			} else if (w1.equals("search")) {
				if (sc2.hasNext()) {
					Search(sc2.nextLine());
				} else {
					System.out.println("No keyword error.");
				}
			} else {
				System.out.println("Unknown Command. Input 'help' for more information.");
			}
			sc2.close();
		}
		sc.close();
		writeData();
	}
}